package cn.xiaolang.thread.lock;

/**
 * 同步锁示例 (类锁和对象锁)
 * 总结：
 * 1.synchronized类锁(*.class)和synchronized对象锁(this,object)不是同一把锁，互不影响
 * 2.synchronized类锁(*.class)和静态同步锁是同一把锁，互斥
 * 3.synchronized对象锁(this,object)和同步锁是同一把锁，互斥
 *
 * @author fuhw/Dean Kano
 * @date 2018-10-30
 */
public class SynchronizedLockStarted {

    public void syncObjLockMethod() {
        // this对象锁
        synchronized (this) {
            this.commonMethod();
        }
    }

    public void syncClassLockMethod() {
        // 类锁
        synchronized (SynchronizedLockStarted.class) {
            this.commonMethod();
        }
    }

    /**
     * synchronized修饰方法
     */
    public synchronized void syncMethod() {
        this.commonMethod();
    }

    /**
     * synchronized修饰方法
     */
    public synchronized void syncMethod2() {
        this.commonMethod();
    }

    /**
     * 普通方法
     */
    public void commonMethod() {
        int i = 5;
        while (i-- > 0) {
            System.out.println(Thread.currentThread().getName() + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * synchronized修饰静态方法
     */
    public static synchronized void syncStaticMethod() {
        int i = 5;
        while (i-- > 0) {
            System.out.println(Thread.currentThread().getName() + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 同步方法之间: 同一把锁,线程阻塞运行
     */
    public static void syncMethodVsSyncMethod(SynchronizedLockStarted cc) {
        new Thread(cc::syncMethod, "syncMethod-").start();
        new Thread(cc::syncMethod2, "syncMethod2-").start();
    }

    /**
     * 同步代码块(this对象锁)vs同步方法 : 同一把锁,线程阻塞运行
     *
     * @author fuhw/Dean Kano
     */
    public static void syncObjLockVsSyncMethod(SynchronizedLockStarted cc) {
        new Thread(cc::syncObjLockMethod, "syncObjLockMethod-").start();
        new Thread(cc::syncMethod, "syncMethod-").start();
    }

    /**
     * 同步代码块(this对象锁)vs普通方法 : 互不影响
     */
    public static void syncObjLockVsCommonMethod(SynchronizedLockStarted cc) {
        new Thread(cc::syncObjLockMethod, "syncObjLockMethod-").start();
        new Thread(cc::commonMethod, "commonMethod-").start();
    }

    /**
     * 同步代码块(this对象锁)vs静态方法(类锁) : 类锁和对象锁是两个不一样的锁，控制着不同的区域，它们是互不干扰的
     */
    public static void syncObjLockVsSyncStaticMethod(SynchronizedLockStarted cc) {
        new Thread(cc::syncObjLockMethod, "syncObjLockMethod-").start();
        new Thread(SynchronizedLockStarted::syncStaticMethod, "syncStaticMethod-").start();
    }

    /**
     * 同步代码块(*.class类锁)vs静态方法(类锁) : synchronized(*.class)和synchronized修饰静态方法是同一把锁
     *
     * @author fuhw/Dean Kano
     */
    public static void syncClassLockVsSyncStaticMethod(SynchronizedLockStarted cc) {
        new Thread(cc::syncClassLockMethod, "syncClassLockMethod-").start();
        new Thread(SynchronizedLockStarted::syncStaticMethod, "syncStaticMethod-").start();
    }


    public static void main(String[] args) {
        SynchronizedLockStarted cc = new SynchronizedLockStarted();

//        syncMethodVsSyncMethod(cc);

//		syncObjLockVsSyncMethod(cc);

//		syncObjLockVsCommonMethod(cc);

//        syncClassLockVsSyncStaticMethod(cc);

//        syncObjLockVsSyncStaticMethod(cc);


        new Thread(cc::syncObjLockMethod, "syncObjLockMethod-").start();
        new Thread(cc::syncMethod, "syncClassLockMethod-").start();

    }

}
